package org.grayrabbit.cms.action.common;

import java.io.InputStream;

import org.apache.commons.lang.StringUtils;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;
import org.grayrabbit.cms.constant.ConfigCode;
import org.grayrabbit.cms.constant.ConstantWebApp;
import org.grayrabbit.cms.constant.ConstantEnum.Module;
import org.grayrabbit.cms.constant.ConstantEnum.OperAct;
import org.grayrabbit.cms.entity.Admin;
import org.grayrabbit.cms.entity.Config;
import org.grayrabbit.cms.service.category.impl.CategoryCache;
import org.grayrabbit.cms.service.system.AdminService;
import org.grayrabbit.cms.service.system.ConfigService;
import org.grayrabbit.cms.util.IpUtil;
import org.grayrabbit.cms.util.RandomCodeMaker;
import org.grayrabbit.cms.vo.system.AdminBean;
import org.grayrabbit.cms.vo.system.LoginInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;


@Controller
@Scope("prototype")
@Namespace("/")
public class LoginAction extends SimpleAction{
	private static final long serialVersionUID = -5956553880365871776L;
	private  static final Logger LOG = LoggerFactory.getLogger(LoginAction.class);
	
	private AdminBean adminBean;
	
	private InputStream inputStream;
	@Autowired
	private AdminService adminService;
	@Autowired
	private ConfigService configService;
	
	@Action(value="test",
			results={
				@Result(name="success",type="velocity",location="/templates/test/view.vm")
			}
			)
	public String test(){
		return SUCCESS;
	}
	
	@Action(value="login")
	public String login(){
		return SUCCESS;
	}  
	 
	/**
	 * 后台管理员用户登录
	 * @return result "success" or "relogin"
	 */
	@Action(value="login-logon",
		results={
			@Result(name="success",type="redirectAction",params={"actionName","go"}),
			@Result(name="relogin",type="redirectAction",params={"actionName","login"})
	})
    public String logon(){
		if(adminBean == null ||StringUtils.isBlank(adminBean.getLoginName()) 
				|| StringUtils.isBlank(adminBean.getPasswd())) 
			return "relogin";
		boolean authFlag = systemConfigIsAuthCode();
		if(authFlag){//系统配置是否启用验证码
			if(!getAuthCode().equalsIgnoreCase(adminBean.getAuthCode())){
				this.addActionError("请输入正确的验证码");
				return "relogin";
			}
		}
		LoginInfo loginInfo = adminService.logon(adminBean.getLoginName(),adminBean.getPasswd());
		String ip = IpUtil.getClientIp(getRequest());
		switch(loginInfo.getLoginState()){
		case notexist:
			LOG.warn("登录帐号为:{},不存在!",adminBean.getLoginName());
			plusLoginFailNum();
			operLogService.addLog(adminBean.getLoginName(), "找不到该用户",
					Module.SYSTEM.getValue(), OperAct.LOGIN.getValue(), null, 
					adminBean.getLoginName()+"用户不存在,登录失败",ip);
			this.addActionError("用户不存在");
			return "relogin";
		case wrongpassword:
			plusLoginFailNum();
			operLogService.addLog(adminBean.getLoginName(), "找不到该用户",
					Module.SYSTEM.getValue(), OperAct.LOGIN.getValue(), null, 
					adminBean.getLoginName()+"密码错误,登录失败",ip);
			this.addActionError("密码错误");
			return "relogin";
		case disabled:
			plusLoginFailNum();
			operLogService.addLog(adminBean.getLoginName(), "找不到该用户",
					Module.SYSTEM.getValue(), OperAct.LOGIN.getValue(), null, 
					adminBean.getLoginName()+"账号已经被禁用,登录失败",ip);
			this.addActionError("账号已经被禁用");
			return "relogin";
		case success:
			clearLoginFailNum();
			setSessionValue(ConstantWebApp.CURRENT_ADMIN,loginInfo.getAdmin());
			setSessionValue(ConstantWebApp.CURRENT_ADMIN_ID, loginInfo.getAdmin().getAdminId());
			setSessionValue(ConstantWebApp.CURRENT_ADMIN_AUTH_CODE, loginInfo.getAdmin().getPerssmins());
			setSessionValue(ConstantWebApp.CURRENT_SITES,loginInfo.getAdmin().getAuthSites());
			if(loginInfo.getAdmin().getAuthSites()!=null&& loginInfo.getAdmin().getAuthSites().size()==1){
				setSessionValue(ConstantWebApp.CURRENT_SITE, loginInfo.getAdmin().getAuthSites().get(0));
			}
			operLogService.addLog(loginInfo.getAdmin().getLoginName(), loginInfo.getAdmin().getRealName(),
					Module.SYSTEM.getValue(), OperAct.LOGIN.getValue(), null, 
					loginInfo.getAdmin().getLoginName()+"成功登录系统",ip);
			//加载成功登陆的用户权限信息   
			return SUCCESS;
		default:
			plusLoginFailNum();
			operLogService.addLog(loginInfo.getAdmin().getLoginName(), loginInfo.getAdmin().getRealName(),
					Module.SYSTEM.getValue(), OperAct.LOGIN.getValue(), null, 
					loginInfo.getAdmin().getLoginName()+"用户不存在,登录失败",ip);
			this.addActionError("用户不存在");
			return "relogin";
		}
    }
    
	//清除登录失败次数
	private void clearLoginFailNum() {
		removeSessionValue("LOGIN_FAIL_NUM");
	}
	//增加登录失败次数
	private void plusLoginFailNum(){
		Integer num = (Integer)getSessionValue("LOGIN_FAIL_NUM");
		if(num==null)
			num = Integer.valueOf(1);
		else
			num = Integer.valueOf(num.intValue()+1);
		setSessionValue("LOGIN_FAIL_NUM", num);
	}
	
	@Action(value="login-authcode",results={
			@Result(name="authCode",type="stream")
	})
	public String authCode() {
		RandomCodeMaker authCode = RandomCodeMaker.getInstance();   
        setInputStream(authCode.getImage());//取得带有随机字符串的图片   
        setSessionValue(ConstantWebApp.AUTH_CODE, authCode.getString());//取得随机字符串放入HttpSession
		return "authCode";
	}
	
	@Action(value="logout",results={
			@Result(name="loginpage",type="redirectAction",params={"actionName","login"})
	})
	public String logout(){
		Admin user = getCurrentAdmin();
		String ip = IpUtil.getClientIp(getRequest());
		if(user != null){
			operLogService.addLog(user.getLoginName(), user.getRealName(),
					Module.SYSTEM.getValue(), OperAct.LOGOUT.getValue(), null, 
					user.getLoginName()+" 退出系统",ip); 
		}
		CategoryCache.removeAuthCatsAndFlagbyAdminIds(getCurrentAdminId());		
		getRequest().getSession().invalidate();		
		return "loginpage";
	}
	
	@Action("nopermission")
	public String noPermission(){		 
		return "nopermission";
	}
	
	@Action(value="login-authcheck")
	public String  authcheck(){ 
		if(adminBean == null ||StringUtils.isBlank(adminBean.getLoginName())) {
			return renderText("{flag:false}"); // true 启用  false 不启用
		}
		boolean flag =systemConfigIsAuthCode();  //系统配置是否启用验证码
		if(!flag){
			return renderText("{flag:false}");
		}else{			
			Admin admin = adminService.getLoginAdmin(adminBean.getLoginName());
			if(admin == null || StringUtils.isBlank(admin.getAdminId()))
				return renderText("{flag:false}");
			int maxNum = loginFailMaxNum();  //系统配置启用验证码的最大错误数量
			int num = admin.getFailNum();
			if(num<maxNum){
				return renderText("{flag:false}");
			}else {
				return renderText("{flag:true}");
			} 
		} 
	}
	/**
	 * 系统配置 是否启用验证码,如后台没有相关配置，则为true
	 * @return
	 */
	private boolean systemConfigIsAuthCode(){
		boolean flag = true;
		Config config= configService.getConfigByAttrKey(ConfigCode.SECURITY_CODE_FLAG);
		if(config != null){
			String isAutnValue = config.getConfigAttrValue();
			if(StringUtils.isNotBlank(isAutnValue) ){
				flag = Boolean.parseBoolean(isAutnValue.trim());
			}
		}
		//当前session已经出错的次数
		Integer current = (Integer)getSessionValue("LOGIN_FAIL_NUM");
		int configLoginFailMaxNum = loginFailMaxNum();//配置定义最大允许出错次数后需要验证码
		return flag?current.intValue()>configLoginFailMaxNum:flag;
	}
	/**
	 * 系统配置的启用验证码的错误次数
	 * @return
	 */
	private int loginFailMaxNum(){
		int failNumMax = 0;  //启用验证码的错误次数
		Config config= configService.getConfigByAttrKey(ConfigCode.SECURITY_CODE_RUN_NUM);
		if(config != null){
			String strNum =  config.getConfigAttrValue();
			if(StringUtils.isNotBlank(strNum)){
				failNumMax = Integer.parseInt(strNum.trim()); 
			}
		}
		return failNumMax;
	}
	
	private String getAuthCode(){
		return (String) getSessionValue(ConstantWebApp.AUTH_CODE);
	}
	
	
	
	
	public AdminBean getAdminBean() {
		return adminBean;
	}
 
	public void setAdminBean(AdminBean adminBean) {
		this.adminBean = adminBean;
	}
 
 
	public InputStream getInputStream() {
		return inputStream;
	}

	public void setInputStream(InputStream inputStream) {
		this.inputStream = inputStream;
	}
 
}
